package top.iflyoung.cim.route.service.impl;

import okhttp3.OkHttpClient;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import top.iflyoung.cim.common.core.proxy.ProxyManager;
import top.iflyoung.cim.common.enums.StatusEnum;
import top.iflyoung.cim.common.exception.CIMException;
import top.iflyoung.cim.common.facade.BaseChatFacade;
import top.iflyoung.cim.common.pojo.CIMUserInfo;
import top.iflyoung.cim.common.pojo.RouteInfo;
import top.iflyoung.cim.common.req.GroupMessageVo;
import top.iflyoung.cim.common.req.P2PMessageVo;
import top.iflyoung.cim.common.util.RouteInfoParseUtil;
import top.iflyoung.cim.common.util.VerifyUtil;
import top.iflyoung.cim.route.api.vo.req.ChatReqVO;
import top.iflyoung.cim.route.api.vo.req.GroupChatReqVo;
import top.iflyoung.cim.route.api.vo.req.LoginReqVO;
import top.iflyoung.cim.route.api.vo.req.P2PReqVO;
import top.iflyoung.cim.route.api.vo.res.CIMServerResVO;
import top.iflyoung.cim.route.api.vo.res.RegisterInfoResVO;
import top.iflyoung.cim.route.service.AccountService;
import top.iflyoung.cim.route.service.UserInfoCacheService;
import top.iflyoung.cim.server.api.ServerApi;
import top.iflyoung.cim.server.api.vo.req.SendMsgReqVO;

import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Function:
 *
 * @author crossoverJie
 * Date: 2018/12/23 21:58
 * @since JDK 1.8
 */
@Service
public class AccountServiceRedisImpl implements AccountService {

    private final static Logger LOGGER = LoggerFactory.getLogger(AccountServiceRedisImpl.class);

    @Autowired
    private UserInfoCacheService userInfoCacheService;

    @Autowired
    private OkHttpClient okHttpClient;

    @Autowired
    @Qualifier("redisChatFacadeService")
    private BaseChatFacade baseChatFacadeService;

    @Override
    public RegisterInfoResVO register(RegisterInfoResVO info) {
        CIMUserInfo userInfo = new CIMUserInfo();
        userInfo.setUserName(info.getUserName());
        userInfo = baseChatFacadeService.register(userInfo);
        return new RegisterInfoResVO(userInfo.getUserId(), userInfo.getUserName());
    }

    @Override
    public StatusEnum login(LoginReqVO loginReqVO) throws Exception {
        CIMUserInfo userInfo = new CIMUserInfo(loginReqVO.getUserId(), loginReqVO.getUserName());
        return baseChatFacadeService.login(userInfo);
    }

    @Override
    public void saveRouteInfo(@NotNull LoginReqVO loginReqVO, @NotNull String msg) throws Exception {
        CIMUserInfo userInfo = new CIMUserInfo(loginReqVO.getUserId(), loginReqVO.getUserName());
        RouteInfo routeInfo = RouteInfoParseUtil.parse(msg);
        baseChatFacadeService.saveChatRouteInfo(userInfo, routeInfo);
    }

    @Override
    public Map<Long, CIMServerResVO> loadRouteRelated(Long groupId) {
        Map<Long, CIMServerResVO> routes = new HashMap<>(64);
        Set<String> groupUserIds = baseChatFacadeService.getMembersByGroupId(groupId);
        parseServerInfo(routes, groupUserIds);
        return routes;
    }

    @Override
    public CIMServerResVO loadRouteRelatedByUserId(Long userId) {
        RouteInfo info = baseChatFacadeService.getUserRouteInfo(userId);
        String value = RouteInfoParseUtil.parse(info);
        if (value == null) {
            throw new CIMException(StatusEnum.OFF_LINE);
        }
        CIMServerResVO cimServerResVO = new CIMServerResVO(RouteInfoParseUtil.parse(value));
        return cimServerResVO;
    }

    private void parseServerInfo(Map<Long, CIMServerResVO> routes, Set<String> groupUserIds) {
        for (String groupUserIdStr : groupUserIds) {
            try {
                Long groupUserId = Long.parseLong(groupUserIdStr);
                routes.put(groupUserId, loadRouteRelatedByUserId(groupUserId));
            } catch (CIMException e) {
                LOGGER.error("Exception", e);
            }
        }

    }


    @Override
    public void pushMsg(CIMServerResVO cimServerResVO, Long sendUserId, ChatReqVO groupReqVO) throws Exception {
        CIMUserInfo cimUserInfo = userInfoCacheService.loadUserInfoByUserId(sendUserId);
        String url = "http://" + cimServerResVO.getIp() + ":" + cimServerResVO.getHttpPort();
        ServerApi serverApi = new ProxyManager<>(ServerApi.class, url, okHttpClient).getInstance();
        SendMsgReqVO vo = new SendMsgReqVO(cimUserInfo.getUserName() + ":" + groupReqVO.getMsg(), groupReqVO.getUserId());
        Response response = null;
        try {
            response = (Response) serverApi.sendMsg(vo);
        } catch (Exception e) {
            LOGGER.error("Exception", e);
        } finally {
            response.body().close();
        }
    }

    @Override
    public void offLine(Long userId) throws Exception {
        baseChatFacadeService.offline(new CIMUserInfo(userId));
    }

    @Override
    public void recordP2PMessage(P2PReqVO p2pReqVo) {
        if (VerifyUtil.isEmpty(p2pReqVo)) {
            throw new NullPointerException("私聊参数为空");
        }
        P2PMessageVo messageVo = new P2PMessageVo(p2pReqVo.getUserId(), p2pReqVo.getReceiveUserId(), p2pReqVo.getMsg());
        baseChatFacadeService.saveP2PMessage(messageVo);
    }

    @Override
    public void recordGroupMessage(GroupChatReqVo groupChatReqVo) {
        if (VerifyUtil.isEmpty(groupChatReqVo)) {
            throw new NullPointerException("群聊参数为空");
        }
        GroupMessageVo messageVo = new GroupMessageVo(groupChatReqVo.getUserId(), groupChatReqVo.getGroupId(), groupChatReqVo.getMsg());
        baseChatFacadeService.saveGroupMessage(messageVo);
    }
}
